home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / editors / mjovesrc.zoo / insert.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  16KB  |  824 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "ctype.h"
  10. #include "list.h"
  11. #include "chars.h"
  12. #include "disp.h"
  13.  
  14. private void
  15.     DoNewline proto((bool indentp));
  16.  
  17. private Bufpos
  18.     *lisp_indent proto((void));
  19.  
  20. /* Make a new line after "after" in buffer "buf", unless "after" is NULL,
  21.    in which case we insert the new line before first line. */
  22.  
  23. Line *
  24. listput(buf, after)
  25. register Buffer    *buf;
  26. register Line    *after;
  27. {
  28.     register Line    *newline = nbufline();
  29.  
  30.     newline->l_prev = after;
  31.     if (after == NULL) {    /* Before the first line */
  32.         newline->l_next = buf->b_first;
  33.         buf->b_first = newline;
  34.     } else {
  35.         newline->l_next = after->l_next;
  36.         after->l_next = newline;
  37.     }
  38.     if (newline->l_next != NULL)
  39.         newline->l_next->l_prev = newline;
  40.     else if (buf != NULL)
  41.         buf->b_last = newline;
  42.     if (buf && buf->b_dot == NULL)
  43.         buf->b_dot = newline;
  44.     return newline;
  45. }
  46.  
  47. /* Divide the current line and move the current line to the next one */
  48.  
  49. void
  50. LineInsert(num)
  51. register int    num;
  52. {
  53.     char    newline[LBSIZE];
  54.     register Line    *newdot,
  55.             *olddot;
  56.     int    oldchar;
  57.  
  58.     olddot = curline;
  59.     oldchar = curchar;
  60.  
  61.     newdot = curline;
  62.     while (--num >= 0) {
  63.         newdot = listput(curbuf, newdot);
  64.         SavLine(newdot, NullStr);
  65.     }
  66.  
  67.     modify();
  68.     if (curchar != 0) {
  69.         strcpy(newline, &linebuf[curchar]);
  70.         linebuf[curchar] = '\0';    /* Shorten this line */
  71.         SavLine(curline, linebuf);
  72.         strcpy(linebuf, newline);
  73.     } else {    /* Redisplay optimization */
  74.         newdot->l_dline = curline->l_dline;
  75.         SavLine(curline, NullStr);
  76.     }
  77.  
  78.     makedirty(curline);
  79.     curline = newdot;
  80.     curchar = 0;
  81.     makedirty(curline);
  82.     IFixMarks(olddot, oldchar, curline, curchar);
  83. }
  84.  
  85. /* Inserts tabs and spaces to move the cursor to column GOAL.  It
  86.    Uses the most optimal number of tabs and spaces no matter what
  87.    was there before hand. */
  88.  
  89. void
  90. n_indent(goal)
  91. register int    goal;
  92. {
  93.     int    dotcol,
  94.         incrmt;
  95.  
  96.     DelWtSpace();
  97.     dotcol = calc_pos(linebuf, curchar);
  98.  
  99.     for (;;) {
  100.         incrmt = (tabstop - (dotcol % tabstop));
  101.         if (dotcol + incrmt > goal)
  102.             break;
  103.         insert_c('\t', 1);
  104.         dotcol += incrmt;
  105.     }
  106.     if (dotcol != goal)
  107.         insert_c(' ', (goal - dotcol));
  108. }
  109.  
  110. #ifdef    ABBREV
  111. void
  112. MaybeAbbrevExpand()
  113. {
  114.     if (MinorMode(Abbrev) && !ismword(LastKeyStruck) &&
  115.         !bolp() && ismword(linebuf[curchar - 1]))
  116.         AbbrevExpand();
  117. }
  118. #endif
  119.  
  120. private void
  121. Insert(c)
  122. int    c;
  123. {
  124.     if (c == CTL('J'))
  125.         LineInsert(arg_value());
  126.     else
  127.         insert_c(c, arg_value());
  128. }
  129.  
  130. void
  131. SelfInsert()
  132. {
  133. #ifdef    ABBREV
  134.     MaybeAbbrevExpand();
  135. #endif
  136.     if (LastKeyStruck != CTL('J') && MinorMode(OverWrite)) {
  137.         register int    num,
  138.                 i;
  139.  
  140.         for (i = 0, num = arg_value(); i < num; i++) {
  141.             int    pos = calc_pos(linebuf, curchar);
  142.  
  143.             if (!eolp()) {
  144.                 if (linebuf[curchar] == '\t') {
  145.                     if ((pos + 1) == ((pos + tabstop) - (pos % tabstop)))
  146.                         del_char(FORWARD, 1, NO);
  147.                 } else
  148.                     del_char(FORWARD, 1, NO);
  149.             }
  150.             insert_c(LastKeyStruck, 1);
  151.         }
  152.     } else
  153.         Insert(LastKeyStruck);
  154.  
  155.     if (MinorMode(Fill) && (curchar >= RMargin ||
  156.                    (calc_pos(linebuf, curchar) >= RMargin))) {
  157.         int margin;
  158.         Bufpos save;
  159.  
  160.         if (MinorMode(Indent)) {
  161.             DOTsave(&save);
  162.             ToIndent();
  163.             margin = calc_pos(linebuf, curchar);
  164.             SetDot(&save);
  165.         } else
  166.             margin = LMargin;
  167.         DoJustify(curline, 0, curline,
  168.               curchar + (int)strlen(&linebuf[curchar]), YES, margin);
  169.     }
  170. }
  171.  
  172. /* insert character C N times at point */
  173. void
  174. insert_c(c, n)
  175. int    c,
  176.     n;
  177. {
  178.     if (n <= 0)
  179.         return;
  180.     modify();
  181.     makedirty(curline);
  182.     ins_c(c, linebuf, curchar, n, LBSIZE);
  183.     IFixMarks(curline, curchar, curline, curchar + n);
  184.     curchar += n;
  185. }
  186.  
  187. /* Tab in to the right place for C mode */
  188.  
  189. void
  190. Tab()
  191. {
  192. #ifdef    LISP
  193.     if (MajorMode(LISPMODE) && (bolp() || !eolp())) {
  194.         int    dotchar = curchar;
  195.         Mark    *m = NULL;
  196.  
  197.         ToIndent();
  198.         if (dotchar > curchar)
  199.             m = MakeMark(curline, dotchar, M_FLOATER);
  200.         (void) lisp_indent();
  201.         if (m) {
  202.             ToMark(m);
  203.             DelMark(m);
  204.         } else
  205.             ToIndent();
  206.         return;
  207.     }
  208. #endif
  209.     if (MajorMode(CMODE)) {
  210.         if (within_indent())
  211.             (void) c_indent(NO);
  212.         else {
  213.             int    curpos,
  214.                 tabbed_pos;
  215.  
  216.             skip_wht_space();
  217.             curpos = calc_pos(linebuf, curchar);
  218.             tabbed_pos = curpos + (CIndIncrmt - (curpos % CIndIncrmt));
  219.             n_indent(tabbed_pos);
  220.         }
  221.     } else
  222.         SelfInsert();
  223. }
  224.  
  225. void
  226. QuotChar()
  227. {
  228.     int    c,
  229.         slow = NO;
  230.  
  231.     c = waitchar(&slow);
  232.     if (c != CTL('@'))
  233.         Insert(c);
  234. }
  235.  
  236. /* Insert the paren.  If in C mode and c is a '}' then insert the
  237.    '}' in the "right" place for C indentation; that is indented
  238.    the same amount as the matching '{' is indented. */
  239.  
  240. int    PDelay = 5,    /* 1/2 a second */
  241.     CIndIncrmt = 8;
  242.  
  243. void
  244. DoParen()
  245. {
  246.     Bufpos    *bp;
  247.     int    tried = NO,
  248.         nx,
  249.         c = LastKeyStruck;
  250.  
  251.     if (!jisclosep(c)) {
  252.         SelfInsert();
  253.         return;
  254.     }
  255.  
  256.     if (MajorMode(CMODE) && c == '}' && within_indent()) {
  257.         bp = c_indent(YES);
  258.         tried = TRUE;
  259.     }
  260. #ifdef    LISP
  261.     if (MajorMode(LISPMODE) && c == ')' && blnkp(linebuf)) {
  262.         bp = lisp_indent();
  263.         tried = TRUE;
  264.     }
  265. #endif
  266.     SelfInsert();
  267. #ifdef    MAC
  268.     if (MinorMode(ShowMatch) && !in_macro()) {
  269. #else
  270.     if (MinorMode(ShowMatch) && !charp() && !in_macro()) {
  271. #endif
  272.         b_char(1);    /* Back onto the ')' */
  273.         if (!tried)
  274.             bp = m_paren(c, BACKWARD, NO, YES);
  275.         f_char(1);
  276.         if (bp != NULL) {
  277.             nx = in_window(curwind, bp->p_line);
  278.             if (nx != -1) {        /* is visible */
  279.                 Bufpos    b;
  280.  
  281.                 DOTsave(&b);
  282.                 SetDot(bp);
  283.                 SitFor(PDelay);
  284.                 SetDot(&b);
  285.             } else
  286.                 s_mess("%s", lcontents(bp->p_line));
  287.         }
  288.         mp_error();    /* display error message */
  289.     }
  290. }
  291.  
  292. void
  293. LineAI()
  294. {
  295.     DoNewline(TRUE);
  296. }
  297.  
  298. void
  299. Newline()
  300. {
  301.     DoNewline(MinorMode(Indent));
  302. }
  303.  
  304. private void
  305. DoNewline(indentp)
  306. bool    indentp;
  307. {
  308.     Bufpos    save;
  309.     int    indent;
  310.  
  311.     /* first we calculate the indent of the current line */
  312.     DOTsave(&save);
  313.     ToIndent();
  314.     indent = calc_pos(linebuf, curchar);
  315.     SetDot(&save);
  316.  
  317. #ifdef    ABBREV
  318.     MaybeAbbrevExpand();
  319. #endif
  320.     if (
  321. #ifdef    LISP
  322.         MajorMode(LISPMODE) ||
  323. #endif
  324.         indentp || blnkp(linebuf))
  325.     {
  326.         DelWtSpace();
  327.     }
  328.  
  329.     /* If there is more than 2 blank lines in a row then don't make
  330.        a newline, just move down one. */
  331.     if (arg_value() == 1 && eolp() && TwoBlank())
  332.         SetLine(curline->l_next);
  333.     else
  334.         LineInsert(arg_value());
  335.  
  336.     if (indentp) {
  337. #ifdef    LISP
  338.         if (MajorMode(LISPMODE))
  339.         (void) lisp_indent();
  340.         else
  341. #endif
  342.         {
  343.         Bol();
  344.         n_indent((LMargin == 0) ? indent : LMargin);
  345.         }
  346.     }
  347. }
  348.  
  349. void
  350. ins_str(str, ok_nl)
  351. register char    *str;
  352. int    ok_nl;
  353. {
  354.     register char    c;
  355.     Bufpos    save;
  356.     int    llen;
  357.  
  358.     if (*str == '\0')
  359.         return;        /* ain't nothing to insert! */
  360.     DOTsave(&save);
  361.     llen = strlen(linebuf);
  362.     while ((c = *str++) != '\0') {
  363.         if (c == '\n' || (ok_nl && llen >= LBSIZE - 2)) {
  364.             IFixMarks(save.p_line, save.p_char, curline, curchar);
  365.             modify();
  366.             makedirty(curline);
  367.             LineInsert(1);
  368.             DOTsave(&save);
  369.             llen = strlen(linebuf);
  370.         }
  371.         if (c != '\n') {
  372.             ins_c(c, linebuf, curchar++, 1, LBSIZE);
  373.             llen += 1;
  374.         }
  375.     }
  376.     IFixMarks(save.p_line, save.p_char, curline, curchar);
  377.     modify();
  378.     makedirty(curline);
  379. }
  380.  
  381. void
  382. open_lines(n)
  383. int    n;
  384. {
  385.     Bufpos    dot;
  386.  
  387.     DOTsave(&dot);
  388.     LineInsert(n);    /* Open the lines... */
  389.     SetDot(&dot);
  390. }
  391.  
  392. void
  393. OpenLine()
  394. {
  395.     open_lines(arg_value());
  396. }
  397.  
  398. /* Take the region FLINE/FCHAR to TLINE/TCHAR and insert it at
  399.    ATLINE/ATCHAR in WHATBUF. */
  400.  
  401. Bufpos *
  402. DoYank(fline, fchar, tline, tchar, atline, atchar, whatbuf)
  403. Line    *fline,
  404.     *tline,
  405.     *atline;
  406. int    fchar,
  407.     tchar,
  408.     atchar;
  409. Buffer    *whatbuf;
  410. {
  411.     register Line    *newline;
  412.     static Bufpos    bp;
  413.     char    save[LBSIZE],
  414.         buf[LBSIZE];
  415.     Line    *startline = atline;
  416.     int    startchar = atchar;
  417.  
  418.     lsave();
  419.     if (whatbuf)
  420.         modify();
  421.     (void) ltobuf(atline, genbuf);
  422.     strcpy(save, &genbuf[atchar]);
  423.  
  424.     (void) ltobuf(fline, buf);
  425.     if (fline == tline)
  426.         buf[tchar] = '\0';
  427.  
  428.     linecopy(genbuf, atchar, &buf[fchar]);
  429.     atline->l_dline = putline(genbuf);
  430.     makedirty(atline);
  431.  
  432.     fline = fline->l_next;
  433.     while (fline != tline->l_next) {
  434.         newline = listput(whatbuf, atline);
  435.         newline->l_dline = fline->